package c.x.jy.forkJoin;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import reactor.core.Fuseable.SynchronousSubscription;

@Service
public class FuckSum {

	@Autowired
	DbUtil db = new DbUtil();

	/**
	 * RecursiveTask有返回值，RecursiveAction无返回值。
	 * 
	 * @author admin
	 *
	 */
	private static class SumTask extends RecursiveTask<Long> {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private int fromId;
		private int endId;
		private DbUtil db;

		public SumTask(Integer fromId, Integer endId, DbUtil db) {
			this.fromId = fromId;
			this.endId = endId;
			this.db = db;

		}

		@Override
		protected Long compute() {
			// TODO
			if (endId - fromId < SingleThread.THRESHOLD) {
				return db.sumRecorders(fromId, endId);
			} else {
				/*
				 * 任务规模较大 定义阀值，继续拆分
				 */
				int mid = (endId - fromId) / 4;

				// SumTask left = new SumTask (fromId, fromId+mid, db);
				// SumTask right = new SumTask ( fromId+mid,endId , db);
				// System.out.println(Thread.currentThread().getName()
				// +"fromId:"+fromId +" endid:"+endId+" mid:"+ mid);
				SumTask left = new SumTask(fromId, fromId + mid, db);
				SumTask left1 = new SumTask(fromId + mid  , fromId + (mid * 2), db);
				SumTask right = new SumTask(fromId + (mid * 2) , fromId + (mid * 3), db);
				SumTask right1 = new SumTask(fromId + (mid * 3)  , endId, db);
				// System.out.println(Thread.currentThread().getName() +" ==>
				// from " + (fromId+(mid*3)+1) +" to " + endId );
				// left.fork();
				// right.fork();
				// left1.fork();
				// right1.fork();
				invokeAll(left, right, left1, right1);
				long leftResult = left.join(); // 左部分结果
				long rightResult = right.join();

				long leftResult1 = left1.join();
				long rightResult1 = right1.join();

				long l = leftResult + rightResult + leftResult1 + rightResult1;

				return l;// leftResult+rightResult;
			}

		}

	}

	public void sum() {
		ForkJoinPool pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors() * 8);

		long start = System.currentTimeMillis();
		int recorMin = db.getMin();
		int recorMax = db.getMax();

		SumTask task = new SumTask(recorMin, recorMax, db);
		pool.invoke(task);
		System.out.println("run ....");
		System.out.println("The sum  is " + task.join() + " spend time :" + (System.currentTimeMillis() - start) + "ms"
				+ " recorMin:" + recorMin + "   recorMax:" + recorMax);
	}

}
